 

package com.hmc.modules.security.config;

import com.hmc.modules.security.oauth2.Oauth2Filter;
import com.hmc.modules.security.oauth2.Oauth2Realm;
import jakarta.servlet.Filter;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.config.ShiroFilterConfiguration;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * Shiro的配置文件
 *
 * @author
 */
@Configuration
public class ShiroConfig {

    /**
     * 创建并配置 DefaultWebSessionManager 实例，用于管理 Web 会话。
     *
     * @return 返回配置好的 DefaultWebSessionManager 实例。
     */
    @Bean
    public DefaultWebSessionManager sessionManager() {
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        sessionManager.setSessionValidationSchedulerEnabled(false); // 禁用会话验证计划器
        sessionManager.setSessionIdUrlRewritingEnabled(false); // 禁用会话 ID URL 重写

        return sessionManager;
    }

    /**
     * 创建 SecurityManager 实例并进行配置，它是 Shiro 安全框架的核心组件。
     *
     * @param oAuth2Realm OAuth2 领域，用于认证和授权。
     * @param sessionManager 会话管理器，用于管理用户会话。
     * @return 返回配置好的 SecurityManager 实例。
     */
    @Bean("securityManager")
    public SecurityManager securityManager(Oauth2Realm oAuth2Realm, SessionManager sessionManager) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(oAuth2Realm); // 设置认证领域
        securityManager.setSessionManager(sessionManager); // 设置会话管理器
        securityManager.setRememberMeManager(null); // 禁用记住我功能

        return securityManager;
    }

    /**
     * 配置并创建 ShiroFilterFactoryBean 实例，它是 Shiro 过滤器链的配置中心。
     *
     * @param securityManager 安全管理器，用于执行安全逻辑。
     * @return 返回配置好的 ShiroFilterFactoryBean 实例。
     */
    @Bean("shiroFilter")
    public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
        ShiroFilterConfiguration config = new ShiroFilterConfiguration();
        config.setFilterOncePerRequest(true); // 配置过滤器仅一次请求

        ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
        shiroFilter.setSecurityManager(securityManager); // 设置安全管理器
        shiroFilter.setShiroFilterConfiguration(config); // 设置 Shiro 过滤器配置

        // Oauth 过滤器配置
        Map<String, Filter> filters = new HashMap<>();
        filters.put("oauth2", new Oauth2Filter());
        shiroFilter.setFilters(filters); // 设置自定义过滤器

        // 定义过滤器链
        Map<String, String> filterMap = new LinkedHashMap<>();
        // 放行指定路径
        filterMap.put("/jmreport/**", "anon");
        filterMap.put("/koTime/**", "anon");
        filterMap.put("/webjars/**", "anon");
        filterMap.put("/druid/**", "anon");
        filterMap.put("/login", "anon");
        filterMap.put("/v3/api-docs/**", "anon");
        filterMap.put("/doc.html", "anon");
        filterMap.put("/views/**", "anon");
        filterMap.put("/captcha", "anon");
        filterMap.put("/favicon.ico", "anon");
        filterMap.put("/pay/alipay/**", "anon");
        filterMap.put("/mp/portal/**", "anon");

        filterMap.put("/**", "oauth2"); // 其他路径使用 Oauth 过滤
        shiroFilter.setFilterChainDefinitionMap(filterMap); // 应用过滤器链定义

        return shiroFilter;
    }

    /**
     * 创建 LifecycleBeanPostProcessor 实例，用于管理 Bean 的生命周期。
     *
     * @return 返回 LifecycleBeanPostProcessor 实例。
     */
    @Bean("lifecycleBeanPostProcessor")
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    /**
     * 创建并配置 AuthorizationAttributeSourceAdvisor 实例，它是一个 AOP 切面，
     * 用于将 Shiro 的权限注解生效。
     *
     * @param securityManager 安全管理器，用于权限检查。
     * @return 返回配置好的 AuthorizationAttributeSourceAdvisor 实例。
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager); // 设置安全管理器
        return advisor;
    }

}